<?php

namespace App\Events;

use App\Models\Machine;
use App\Models\User;
use App\Services\EchoServer;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\DB;

/**
 * 围观者发生变化
 *
 * Class SpectatorsChanged
 * @package App\Events
 */
class SpectatorsChanged implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    /**
     * 游戏机
     *
     * @var \App\Models\Machine
     */
    protected $machine;
    
    /**
     * 频道名称
     *
     * @var string
     */
    protected $channel;

    public function __construct(Machine $machine)
    {
        $this->machine = $machine;

        $this->channel = "machines.{$this->machine->id}.spectators";
    }

    /**
     * 广播频道：machines.{machine_id}.spectators
     *
     * @return \Illuminate\Broadcasting\PresenceChannel
     */
    public function broadcastOn()
    {
        return new PresenceChannel($this->channel);
    }
    
    /**
     * 事件名：spectators.changed
     *
     * @return string
     */
    public function broadcastAs()
    {
        return snake_case(class_basename(self::class), '.');
    }
    
    /**
     * 事件参数
     *
     * @return array
     */
    public function broadcastWith()
    {
        /** @var EchoServer $echoServer */
        $echoServer = app(EchoServer::class);
        $members = $echoServer->getMembers($this->channel);
        $count = count($members);
        
        // 可能存在同一用户在多终端访问的情况，先获取 15 个，再去重
        $memberIds = array_column(array_slice($members, -15), 'user_id');
        $userIds = array_slice(array_unique(array_reverse($memberIds)), 0, 4);
        
        if ($this->machine->isWorking()) {
            // 操作者的头像不展示在围观中
            array_remove($userIds, $this->machine->latest_user_id);
            
            $count -= 1;
        }
    
        $avatars = [];
        if ($userIds) {
            $userIds = array_slice($userIds, 0, 3);
            $idsStr = implode(',', $userIds);
            $users = User::whereIn('id', $userIds)->orderByRaw(DB::raw("FIELD(id, {$idsStr})"))->get();
            
            $avatars = $users->map(function ($user) {
                return image_url($user->avatar);
            });
        }
        
        return [
            'avatars' => $avatars,
            'count' => $count,
        ];
    }
}
